package org.marketing.common.util;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;

import org.marketing.common.exception.UtilException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * MAP和对象相互转换的工具类
 * 
 * @author BENJAMIN
 *
 */
public class MapConverUtil {

	private static Logger log = LoggerFactory.getLogger(MapConverUtil.class);

	/**
	 * 对象转MAP，会全部转成大写key
	 * 
	 * @param o
	 * @return
	 * @throws Exception
	 */
	public static Map<String, Object> PO2Map(Object o) {
		Map<String, Object> map = new HashMap<>();
		String clzName = o.getClass().getSimpleName();
		log.info("类：" + o.getClass().getName());
		Field[] fields = o.getClass().getDeclaredFields();
		log.info("***" + clzName + "转map开始****");
		try {
			for (Field field : fields) {
				field.setAccessible(true);
				String proName = field.getName();
				Object proValue = field.get(o);
				map.put(proName.toUpperCase(), proValue);
//				log.info("key：" + proName + "value:" + proValue);

			}
		} catch (Exception e) {
			log.error("***" + e.getMessage(), e);
		}
		log.info("***" + clzName + "转map结束****");
		return map;
	}
	/**
	 * 对象转MAP，会全部转成大写key
	 * 
	 * @param o
	 * @param ot 用于提示的实体类
	 * @return
	 * @throws Exception
	 */
	public static String NotNullPO2Map(Object o,Object ot,String ... str) {
		String result = "";
		String clzName = o.getClass().getSimpleName();
		log.info("类：" + o.getClass().getName());
		Field[] fields = o.getClass().getDeclaredFields();
		Field[] fieldsTi = ot.getClass().getDeclaredFields();
		log.info("***" + clzName + "校验Object开始****");
		try {
			for (Field field : fields) {
				field.setAccessible(true);
				boolean flag = false;
				String proName = field.getName();
				Object proValue = field.get(o);
				for (String s : str) {
					if(proName.equals(s)){
						flag=true;
						break;
					}
				}
				if(flag){
					continue;
				}
				log.info("参数名：" + proName + "    参数名值:" + proValue);
				if(CheckUtil.NullOrEmpty(proValue)||"".equals(proValue)){
					for (Field f : fieldsTi) {
						f.setAccessible(true);
						String proName1 = f.getName();
						Object proValue1 = f.get(ot);
						if(proName.equals(proName1)){
							result= proValue1+"不能为空";
							break;
						}
					}
					break;
				}
			}
		} catch (Exception e) {
			log.error("***" + e.getMessage(), e);
		}
		log.info("***" + clzName + "校验Object结束****");
		return result;
	}
	/**
	 * 对象转MAP，会全部转成大写key
	 * 
	 * @param o
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("rawtypes")
	public static Map<String, Object> RequestPO2Map(ServletRequest IdrealerStatus,Object o) {
		log.info("***ServletRequest的参数****");
		Enumeration paramNames = IdrealerStatus.getParameterNames();  
        while (paramNames.hasMoreElements()) {  
            String paramName = (String) paramNames.nextElement();  
  
            String[] paramValues = IdrealerStatus.getParameterValues(paramName);  
            if (paramValues.length == 1) {  
                String paramValue = paramValues[0];  
                log.info("**参数****key:" +paramName +"    value:"+paramValue);
            }  
        } 
        log.info("***ServletRequest的参数****");
		Map<String, Object> map = new HashMap<>();
		log.info("类：" + o.getClass().getName());
		Field[] fields = o.getClass().getDeclaredFields();
		log.info("***ServletRequest转map开始****");
		try {
			for (Field field : fields) {
				field.setAccessible(true);
				String proName = field.getName();
				String pa = IdrealerStatus.getParameter(proName);
				if(CheckUtil.NullOrEmpty(pa)){
					continue;
				}
				map.put(proName, pa);
				log.info("key：" + proName + "    value:" + pa);
			}
		} catch (Exception e) {
			log.error("***" + e.getMessage(), e);
		}
		log.info("***ServletRequest转map结束****");
		return map;
	}
	/**
	 * 一个对象转另一个对象(App专用)
	 * 
	 * @param src  源对象
	 * @param o  目标对象 (注：目标对象中的字段在源对象中存在，且字段名一样)(目标对象所有属性类型String)
	 * @return o
	 */
	@SuppressWarnings("rawtypes")
	public static void ObjectToAppObject(Object src,Object o) {
		try {
			log.info("源对象：" + src.getClass().getName());
			log.info("目标对象：" + o.getClass().getName());
			log.info("***ObjectToAppObject的转换开始****");
			Field[] fields=o.getClass().getDeclaredFields();
	        Field[] srcfields=src.getClass().getDeclaredFields(); 
	        for(Field field : fields){ 
	        	String name = field.getName();
	        	int mod = field.getModifiers();
				if (Modifier.isStatic(mod) || Modifier.isFinal(mod)) {
					continue;
				}
	        	for(Field srcfield : srcfields){ 
	        		Class c = srcfield.getType();
	            	String srcName = srcfield.getName();
	            	field.setAccessible(true);
	            	if(name.equals(srcName) && c == Date.class){
	            		Object obj = getFieldValueByName(name, src);
	            		String s = "";
	            		if(obj!=null){
	            			s = DateUtil.formateDate((Date) obj, "yyyy-MM-dd HH:mm:ss");
	            		}
	            		field.set(o, s);
	            		break;
	            	}else if(name.equals(srcName)){
	            		Object obj = getFieldValueByName(name, src);
	            		String s = "";
	            		if(obj!=null){
	            			s = obj.toString();
	            		}
	            		field.set(o, s);
	            		break;
	            	}
	            	
	            } 
	        } 
		} catch (Exception e) {
			log.error("***" + e.getMessage(), e);
		}
		log.info("***ObjectToAppObject的转换结束****");
	}
	private static Object getFieldValueByName(String fieldName, Object o) {  
        try {    
            String firstLetter = fieldName.substring(0, 1).toUpperCase();    
            String getter = "get" + firstLetter + fieldName.substring(1);    
            Method method = o.getClass().getMethod(getter, new Class[] {});    
            Object value = method.invoke(o, new Object[] {});    
            return value;    
        } catch (Exception e) {    
            log.error(e.getMessage(),e);    
            return null;    
        }    
    } 
	/**
     * 对象转MAP，会全部转成大写key
     * 
     * @param o
     * @return
     * @throws Exception
     */
    public static Map<String, Object> RequestPO2Map(HttpServletRequest IdrealerStatus,Object o) {
        Map<String, Object> map = new HashMap<>();
        log.info("类：" + o.getClass().getName());
        Field[] fields = o.getClass().getDeclaredFields();
        log.info("***ServletRequest转map开始****");
        try {
            for (Field field : fields) {
                field.setAccessible(true);
                String proName = field.getName();
                String pa = IdrealerStatus.getParameter(proName);
                if(CheckUtil.NullOrEmpty(pa)){
                    continue;
                }
                map.put(proName, pa);
                log.info("key：" + proName + "    value:" + pa);
            }
        } catch (Exception e) {
            log.error("***" + e.getMessage(), e);
        }
        log.info("***ServletRequest转map结束****");
        return map;
    }
	/**
	 * MAP转对象，不严格匹配，仅返回包含的字段
	 * 
	 * @param map
	 * @param o
	 * @return
	 * @throws Exception
	 */
	public static Object map2PO(Map<String, Object> map, Object o) {
		try {
			if (!map.isEmpty()) {
				for (Map.Entry<String, Object> entry : map.entrySet()) {
					Field[] fields = o.getClass().getDeclaredFields();
					String clzName = o.getClass().getSimpleName();
					log.info("类：" + o.getClass().getName());
					log.info("***map转" + clzName + "开始****");
					for (Field field : fields) {
						int mod = field.getModifiers();
						if (Modifier.isStatic(mod) || Modifier.isFinal(mod)) {
							continue;
						}

						if (field.getName().toUpperCase().equals(entry.getKey())
								|| field.getName().equals(entry.getKey())) {
							Class c = field.getType();
							field.setAccessible(true);
							if (entry.getValue() != null && c == Long.class) {
								field.set(o, new Long(entry.getValue().toString()));
							} else if (entry.getValue() != null && c == Date.class) {
								Class tmp = entry.getValue().getClass();
								if (tmp == Long.class) {
									Date a = new Date(new Long(entry.getValue().toString()));
									field.set(o, a);
								} else {
									field.set(o, entry.getValue());
								}
							} else {
								field.set(o, entry.getValue());
							}
							log.info("key：" + entry.getKey() + "value:" + entry.getValue());
						}

					}
					log.info("***map转" + clzName + "结束****");
				}
			}
		} catch (Exception e) {
			log.error("***" + e.getMessage(), e);
		}
		return o;
	}

	/**
	 * 严格匹配每个字段 支持全大小 有字段未在Map中找到会抛出异常
	 * 
	 * @param map
	 * @param o
	 * @return
	 * @throws Exception
	 */
	public static Object map2POStrict(Map<String, Object> map, Object o) {
		try {
			if (!map.isEmpty()) {
				Field[] fields = null;
				fields = o.getClass().getDeclaredFields();
				log.info("类：" + o.getClass().getName());

				for (Field field : fields) {
					int mod = field.getModifiers();
					Class c = field.getType();
					if (Modifier.isStatic(mod) || Modifier.isFinal(mod)) {
						continue;
					}

					boolean isfind = false;
					for (Map.Entry<String, Object> entry : map.entrySet()) {
						if (field.getName().toUpperCase().equals(entry.getKey())
								|| field.getName().equals(entry.getKey())) {
							isfind = true;
							field.setAccessible(true);

							if (entry.getValue() != null && c == Long.class) {
								field.set(o, new Long(entry.getValue().toString()));
							} else if (entry.getValue() != null && c == Date.class) {
								Class tmp = entry.getValue().getClass();
								if (tmp == Long.class) {
									Date a = new Date(new Long(entry.getValue().toString()));
									field.set(o, a);
								} else {
									field.set(o, entry.getValue());
								}
							} else {
								field.set(o, entry.getValue());
							}

							log.info("key：" + entry.getKey() + "value:" + entry.getValue());
						}
					}
					if (!isfind) {
						log.error("没用找到字段" + field.getName() + "在map中对应的映射");
						throw new UtilException("没用找到字段" + field.getName() + "在map中对应的映射");
					}
				}

			}
		} catch (Exception e) {
			log.error("***" + e.getMessage(), e);
		}
		return o;
	}
}